package com.softeem.spider;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Spider {

    private Pattern pattern;
    private String url;
    private String regex;
    private String downloadDir;

    public void setUrl(String url) {
        this.url = url;
    }

    public void setRegex(String regex) {
        this.regex = regex;
    }

    public void setDownloadDir(String downloadDir) {
        this.downloadDir = downloadDir;
    }

    private void init() {
        pattern = Pattern.compile(regex);
    }

    /**
     * 获取所有资源地址
     *
     * @return
     */
    private ArrayList<String> resources() {
        //初始化
        init();
        //创建集合存储所有资源地址
        ArrayList<String> list = new ArrayList<>();
        //读取网页源代码
        String html = HttpUtils.readAsText(url);
        //获取匹配器
        Matcher m = pattern.matcher(html);
        String protocol = "";
        while (m.find()) {
            String url = m.group();
            System.out.println("获取资源地址:" + url);
            //判断url地址中是否包含http或者https协议头
            if (!url.matches("^(http|https)://.*$")) {
                //获取请求协议
                protocol = this.url.split(":")[0] + "://";
            }
            //添加资源地址到集合中
            list.add(protocol + url);
        }
        return list;
    }

    /**
     * 检查并创建目录
     */
    private File checkOrCreateDir() {
        //创建目录对象
        File dir = new File(downloadDir);
        if (!dir.exists()) {
            //创建目录
            if (dir.mkdirs()) {
                LogUtils.log("目录创建成功" + dir.getAbsolutePath());
                System.out.println("目录创建成功:" + dir.getAbsolutePath());
            }
        }
        return dir;
    }

    /**
     * 下载
     */
    public void download() {
        File dir = checkOrCreateDir();
        ArrayList<String> resources = resources();
        LogUtils.log("资源集合:" + resources);
        //循环遍历资源地址并启用线程下载文件
        resources.forEach(url -> {
            //使用线程池下载文件
            ExecutorService es = Executors.newFixedThreadPool(5);
            es.execute(()->{
                System.out.println(Thread.currentThread().getId());
                //读取url资源为输入流
                InputStream in = HttpUtils.readAsStream(url);
                //获取文件名
                String fname = getFileName(url);
                try {
                    //根据目录名称和文件名新建文件对象
                    File target = new File(dir, fname);
                    //文件传输
                    in.transferTo(new FileOutputStream(target));
                    LogUtils.log("文件传输完成:" + target.getAbsolutePath());
                    System.out.println("下载完成:" + target.getAbsolutePath());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            });
            //关闭线程池
            es.shutdown();
        });
    }

    /**
     * 获取文件名
     *
     * @param url
     * @return
     */
    private String getFileName(String url) {
        int index = url.lastIndexOf("/");
        return url.substring(index + 1);
    }

}
